﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Data.OleDb;
using System.Text.RegularExpressions;
using System.IO;
using System.Collections.Generic;
using BaseSet.Entity.Common.Text;
using Brettle.Web.NeatUpload;

namespace BaseSet.Entity.Common.DataOperation
{
    public class FileOperation
    {
        #region -- 导出 --

        /// <summary>
        /// 导出Excel格式数据 数据源是 DataTable
        /// </summary>
        /// <param name="page">所在页</param>
        /// <param name="fileName">文件名</param>
        /// <param name="data">数据源</param>
        /// <param name="columnNames">要显示的列名 与fieldNames对应</param>
        /// <param name="fieldNames">数据源的列名</param>
        /// <param name="haveOrderNum">是否带序号</param>
        /// <returns>是否成功</returns>
        public static bool ExportToExcel(Page page, string fileName, DataTable data, string[] columnNames, string[] fieldNames, bool haveOrderNum)
        {
            if (data == null || data.Rows.Count == 0)
            {
                return false;
            }

            if (fieldNames == null || fieldNames.Length == 0)
            {
                fieldNames = Tools.GetColumnNames(data);
            }

            if (columnNames == null || columnNames.Length == 0)
            {
                columnNames = fieldNames;
            }

            string content = getTableFromDataTable(data, columnNames, fieldNames, haveOrderNum);

            page.Response.Clear();
            page.Response.Buffer = true;
            page.Response.Charset = "GB2312";//"UTF-8"
            page.Response.AppendHeader("Content-Disposition", "attachment;filename=" + fileName + System.DateTime.Now.ToString("_yyMMdd_hhmm") + ".xls");
            page.Response.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");//设置输出流为简体中文
            page.Response.ContentType = "application/ms-excel";//设置输出文件类型为excel文件。 
            page.EnableViewState = false;
            page.Response.Write(content);
            page.Response.End();

            return true;
        }
        // 将List中的对象集拼接为表格 输出为字符串 columnNames:要显示的列名（表头） fieldNames:对象的属性名
        private static string getTableFromDataTable(DataTable data, string[] columnNames, string[] fieldNames, bool haveOrderNum)
        {
            StringBuilder sb = new StringBuilder();

            //将要输出的文件头
            sb.AppendLine("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=gb2312\">");

            //将要输出的文件内容
            sb.AppendLine("<table cellspacing=\"0\" cellpadding=\"5\" rules=\"all\" border=\"1\">");

            //表头
            sb.AppendLine("<tr style=\"font-weight: bold; white-space: nowrap;\">");
            if (haveOrderNum)
            {
                sb.AppendLine("<td>序号</td>");
            }
            for (int cid = 0; cid < columnNames.Length; cid++)
            {
                sb.AppendLine("<td>" + columnNames[cid] + "</td>");
            }
            sb.AppendLine("</tr>");

            //内容
            string fieldValue = "";
            for (int i = 0; i < data.Rows.Count; i++)
            {
                sb.Append("<tr>");
                if (haveOrderNum)
                {
                    sb.AppendLine("<td>" + (i + 1) + "</td>");
                }

                for (int j = 0; j < fieldNames.Length; j++)
                {
                    fieldValue = data.Rows[i][fieldNames[j]] + "";
                    sb.Append("<td>" + fieldValue + "</td>");
                }
                sb.AppendLine("</tr>");
            }

            sb.AppendLine("</table>");

            return sb.ToString();
        }
        /// <summary>
        /// 导出Excel格式数据
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="page">所在页</param>
        /// <param name="fileName">文件名</param>
        /// <param name="list">数据源</param>
        /// <param name="columnNames">要显示的列名 与fieldNames对应</param>
        /// <param name="fieldNames">对象的属性名</param>
        /// <param name="maps">扩展的字段  key:fields  value:valueList</param>
        /// <param name="haveOrderNum">是否带序号</param>
        /// <returns></returns>
        public static bool ExportToExcel<T>(Page page, string fileName, IList<T> list, string[] columnNames, string[] fieldNames, Dictionary<string, IList<Object>> maps, bool haveOrderNum)
        {
            if (list == null || list.Count == 0)
            {
                return false;
            }

            if (fieldNames == null || fieldNames.Length == 0)
            {
                fieldNames = Tools.GetPropertyNames<T>();
            }

            if (columnNames == null || columnNames.Length == 0)
            {
                columnNames = fieldNames;
            }

            string content = getTableFromList<T>(list, columnNames, fieldNames, maps,haveOrderNum);

            page.Response.Clear();
            page.Response.Buffer = true;
            page.Response.Charset = "GB2312";//"UTF-8"
            page.Response.AppendHeader("Content-Disposition", "attachment;filename=" + fileName + System.DateTime.Now.ToString("_yyMMdd_hhmm") + ".xls");
            page.Response.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");//设置输出流为简体中文
            page.Response.ContentType = "application/ms-excel";//设置输出文件类型为excel文件。 
            page.EnableViewState = false;
            page.Response.Write(content);
            page.Response.End();

            return true;
        }
        // 将List中的对象集拼接为表格 输出为字符串 columnNames:要显示的列名（表头） fieldNames:对象的属性名
        private static string getTableFromList<T>(IList<T> list, string[] columnNames, string[] fieldNames, Dictionary<string, IList<Object>> maps,bool haveOrderNum)
        {
            StringBuilder sb = new StringBuilder();

            //将要输出的文件头
            sb.AppendLine("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=gb2312\">");

            //将要输出的文件内容
            sb.AppendLine("<table cellspacing=\"0\" cellpadding=\"5\" rules=\"all\" border=\"1\">");

            //表头
            sb.AppendLine("<tr style=\"font-weight: bold; white-space: nowrap;\">");
            if (haveOrderNum)
            {
                sb.AppendLine("<td>序号</td>");
            }
            for (int cid = 0; cid < columnNames.Length; cid++)
            {
                sb.AppendLine("<td>" + columnNames[cid] + "</td>");
            }
            sb.AppendLine("</tr>");

            //内容
            string fieldValue = "";
            string viewName = string.Empty;
            bool viewValue = false; 
            Type listType = list[0].GetType();
            for (int i = 0; i < list.Count; i++)
            {
                sb.Append("<tr>");
                if (haveOrderNum)
                {
                    sb.AppendLine("<td>" + (i + 1) + "</td>");
                }

                for (int j = 0; j < fieldNames.Length; j++)
                {
                    if (listType.GetProperty(fieldNames[j]) != null)
                    {
                        viewName = fieldNames[j] + "_View_Status";
                        viewValue = Convert.ToBoolean(listType.GetProperty(viewName).GetValue(list[i], null));
                        if (viewValue)
                        {
                            fieldValue = Tools.GetPropertyValue<T>(list[i], fieldNames[j]) + "";
                        }
                        else
                        {
                            fieldValue = "";
                        }
                    }
                    else
                    {
                        fieldValue = maps[fieldNames[j]][i] + "";
                    }
                    sb.Append("<td>" + fieldValue + "</td>");
                }
                sb.AppendLine("</tr>");
            }

            sb.AppendLine("</table>");

            return sb.ToString();
        }
        
        /// <summary>
        /// 导出CSV格式数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="page">当前页</param>
        /// <param name="fileName">文件名</param>
        /// <param name="list">数据源</param>
        /// <param name="columnNames">要显示的列名 与fieldNames对应</param>
        /// <param name="fieldNames">对象的属性名</param>
        public static void ExportToCSV<T>(Page page, string fileName, IList<T> list, string[] columnNames, string[] fieldNames)
        {
            if (list == null || list.Count == 0)
            {
                return;
            }

            if (fieldNames == null || fieldNames.Length == 0)
            {
                fieldNames = Tools.GetPropertyNames<T>();
            }

            if (columnNames == null || columnNames.Length == 0)
            {
                columnNames = fieldNames;
            }

            string content = getStringFromList<T>(list, columnNames, fieldNames);

            byte[] btyeUTF16 = { 0xFF, 0xFE };    //unicode 头标示
            page.Response.Clear();
            page.Response.Charset = "utf-16";
            page.Response.Buffer = true;
            page.EnableViewState = false;
            page.Response.ContentEncoding = System.Text.UnicodeEncoding.Unicode;
            page.Response.ContentType = "text/csv";
            //page.Response.AppendHeader("Content-Length", (2*data.Length).ToString());
            page.Response.AppendHeader("Content-Disposition", "attachment;filename=" + fileName + System.DateTime.Now.ToString("_yyMMdd_hhmm") + ".csv");
            page.Response.BinaryWrite(btyeUTF16);    //写文件头    Byte Order Mark
            page.Response.Write(content);   //写文件内容
            page.Response.Flush();
            page.Response.End();
        }
        //将List中的对象集拼接为CSV的字符串
        private static string getStringFromList<T>(IList<T> list, string[] columnNames, string[] fieldNames)
        {
            StringBuilder sb = new StringBuilder();

            //写出列名
            foreach (string column in columnNames)
            {
                sb.Append("\"");
                sb.Append(column.Replace("\"", "\"\""));
                sb.Append("\"");
                sb.Append("\t");
            }
            sb.Append("\n");

            //写出数据
            foreach (T row in list)
            {
                foreach (string field in fieldNames)
                {
                    sb.Append("\"");
                    sb.Append((Tools.GetPropertyValue(row, field) + "").Replace("\"", "\"\""));
                    sb.Append("\"");
                    sb.Append("\t");
                }
                sb.Append("\n");
            }

            sb.Append("\n");

            return sb.ToString();
        }

        /// <summary>
        /// 导出XML格式数据
        /// </summary>
        /// <param name="ds">数据源</param>
        /// <param name="columnNames">当columnNames为空时，将导出所有字段;有则导出提供的字段</param>
        public static void ExportXML<T>(IList<T> list, string[] columnNames)
        {
            if (list == null || list.Count == 0)
            {
                return;
            }

            if (columnNames == null || columnNames.Length == 0)
            {
                columnNames = Tools.GetPropertyNames<T>();
            }

            string data = getXMLStrFromList(list, columnNames);

            string temp = string.Format("attachment;filename={0}", System.DateTime.Now.ToString("yyyyMMddhhmmss") + System.IO.Path.GetFileName(System.IO.Path.GetTempFileName()) + ".xml");
            System.Web.HttpContext.Current.Response.ClearHeaders();
            //System.Web.HttpContext.Current.Response.Charset = "UTF-8";
            System.Web.HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.GetEncoding("gb2312");
            System.Web.HttpContext.Current.Response.HeaderEncoding = System.Text.Encoding.GetEncoding("gb2312");
            System.Web.HttpContext.Current.Response.AppendHeader("Content-disposition", temp);
            System.Web.HttpContext.Current.Response.Write(data);
            System.Web.HttpContext.Current.Response.End();
        }
        //将List中的对象集拼接为XML的字符串
        private static string getXMLStrFromList<T>(IList<T> list, string[] columnNames)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("<?xml version=\"1.0\"?>");
            sb.Append("<?mso-application progid=\"Excel.Sheet\"?>");
            sb.Append("<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"");
            sb.Append(" xmlns:o=\"urn:schemas-microsoft-com:office:office\"");
            sb.Append(" xmlns:x=\"urn:schemas-microsoft-com:office:excel\"");
            sb.Append(" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"");
            sb.Append(" xmlns:html=\"http://www.w3.org/TR/REC-html40\">");
            sb.Append("<Styles><Style ss:ID=\"DefaultStyle\" ss:Name=\"Normal\"><Alignment ss:Vertical=\"Center\"/><Borders/><Font ss:FontName=\"宋体\" x:CharSet=\"134\" ss:Size=\"12\"/><Interior/><NumberFormat/><Protection/></Style>");
            sb.Append("<Style ss:ID=\"s21\"><NumberFormat ss:Format=\"@\"/></Style></Styles><Worksheet ss:Name=\"Data\"><Names><NamedRange ss:Name=\"_FilterDatabase\"  ss:Hidden=\"1\"/></Names><Table>");

            //写出列名
            sb.Append("<Row>");
            foreach (string column in columnNames)
            {
                sb.Append("<Cell ss:StyleID=\"s21\"><Data ss:Type=\"String\">");
                sb.Append(column);
                sb.Append("</Data><NamedCell ss:Name=\"_FilterDatabase\"/></Cell>");
            }
            sb.Append("</Row>");

            //写出数据
            foreach (T row in list)
            {
                sb.Append("<Row>");
                foreach (string column in columnNames)
                {
                    sb.Append("<Cell><Data ss:Type=\"String\">");
                    sb.Append((Tools.GetPropertyValue(row, column) + "").Replace("\"", "\"\""));
                    sb.Append("</Data></Cell>");
                }
                sb.Append("</Row>");

            }
            sb.Append("</Table>");

            sb.Append("<AutoFilter x:Range=\"R1C1:R1C" + columnNames.Length + "\" xmlns=\"urn:schemas-microsoft-com:office:excel\"></AutoFilter>");
            sb.Append("<Sorting xmlns=\"urn:schemas-microsoft-com:office:excel\"><Sort>Sort</Sort></Sorting></Worksheet></Workbook>");

            return sb.ToString();
        }

        #endregion

        #region -- 文件上传 已整理 --

        /// <summary>
        /// 文件上传 已优化 （这里的提示语是写死的 进一步优化：返回出错状态值 由调用者决定给用户什么提示）
        /// </summary>
        /// <param name="upFile">上传的文件</param>
        /// <param name="allowExts">允许的文件扩展名 字符串数组 如果为NULL 表示可以上传所有类型的文件 如果为一个没有元素的数组 表示什么文件都不能上传</param>
        /// <param name="allowSize">允许的文件大小 如400,0000（超过4000000 可能回发不了 需做进一步设定）</param>
        /// <param name="uploadPath">要将文件上传到的站点物理路径</param>
        /// <param name="output">输出信息 上传成功输出新的文件名 失败输出失败原因</param>
        /// <returns>返回上传是否成功 true:成功 false:失败</returns>
        public static bool UploadFile(HttpPostedFile upFile, string[] allowExts, int allowSize, string uploadPath, ref string output)
        {
            #region -- 检查必须要素 --

            if (upFile == null)
            {
                output = "未上传文件！";
                return false;
            }

            if (uploadPath == null)
            {
                output = "未提供上传路径！";
                return false;
            }

            #endregion

            // 原始文件名
            string fileName = upFile.FileName;

            #region -- 检查文件扩展名 --

            string extName = fileName.Substring(fileName.LastIndexOf('.'));
            if (allowExts != null)
            {
                if (allowExts.Length == 0)
                {
                    output = "未提供允许上传的文件类型！";
                    return false;
                }

                bool correctType = false;
                for (int aeid = 0; aeid < allowExts.Length; aeid++)
                {
                    if (extName.ToLower() == allowExts[aeid].ToLower())
                    {
                        correctType = true;
                        break;
                    }
                }
                if (!correctType)
                {
                    output = "上传的文件格式不正确！";
                    return false;
                }
            }

            #endregion

            #region -- 检查文件大小 --

            if (upFile.ContentLength > allowSize)
            {
                output = "文件大小超过限制！";
                return false;
            }

            #endregion

            // 新的文件名 不包括路径 如果需要全名 调用处已知路径 加上文件名就可以了
            fileName = string.Format("{0}{1}", Guid.NewGuid(), extName);

            #region -- 保存文件 --

            // 如果不存在上传目录 则创建
            if (!Directory.Exists(uploadPath))
            {
                Directory.CreateDirectory(uploadPath);
            }

            // 文件全名
            string fullName = uploadPath + fileName;
            // 保存文件
            upFile.SaveAs(fullName);
            if (!File.Exists(fullName))
            {
                output = "文件保存失败！";
                return false;
            }

            #endregion

            // 保存文件成功 返回新的文件名
            output = fileName;
            return true;
        }

        /// <summary>
        /// 文件上传 异步
        /// </summary>
        /// <param name="upFile">上传的文件</param>
        /// <param name="allowExts">允许的文件扩展名 字符串数组 如果为NULL 表示可以上传所有类型的文件 如果为一个没有元素的数组 表示什么文件都不能上传</param>
        /// <param name="allowSize">允许的文件大小 如400,0000（超过4000000 可能回发不了 需做进一步设定）</param>
        /// <param name="uploadPath">要将文件上传到的站点物理路径</param>
        /// <param name="output">输出信息 上传成功输出新的文件名 失败输出失败原因</param>
        /// <returns>返回上传是否成功 true:成功 false:失败</returns>
        public static bool UploadFileAjax(InputFile upFile, string[] allowExts, int allowSize, string uploadPath, ref string output)
        {
            #region -- 检查必须要素 --

            if (!upFile.HasFile)
            {
                output = "未上传文件！";
                return false;
            }

            if (uploadPath == null)
            {
                output = "未提供上传路径！";
                return false;
            }

            #endregion

            // 原始文件名
            string fileName = upFile.FileName;

            #region -- 检查文件扩展名 --

            string extName = fileName.Substring(fileName.LastIndexOf('.'));
            if (allowExts != null)
            {
                if (allowExts.Length == 0)
                {
                    output = "未提供允许上传的文件类型！";
                    return false;
                }

                bool correctType = false;
                for (int aeid = 0; aeid < allowExts.Length; aeid++)
                {
                    if (extName.ToLower() == allowExts[aeid].ToLower())
                    {
                        correctType = true;
                        break;
                    }
                }
                if (!correctType)
                {
                    output = "上传的文件格式不正确！";
                    return false;
                }
            }

            #endregion

            #region -- 检查文件大小 --

            if (upFile.ContentLength > allowSize)
            {
                output = "文件大小超过限制！";
                return false;
            }

            #endregion

            // 新的文件名 不包括路径 如果需要全名 调用处已知路径 加上文件名就可以了
            fileName = string.Format("{0}{1}", Guid.NewGuid(), extName);

            #region -- 保存文件 --

            // 如果不存在上传目录 则创建
            if (!Directory.Exists(uploadPath))
            {
                Directory.CreateDirectory(uploadPath);
            }

            // 文件全名
            string fullName = uploadPath + fileName;
            // 保存文件
            upFile.MoveTo(fullName, MoveToOptions.Overwrite);
            if (!File.Exists(fullName))
            {
                output = "文件保存失败！";
                return false;
            }

            #endregion

            // 保存文件成功 返回新的文件名
            output = fileName;
            return true;
        }

        #endregion

        #region -- 文件下载 已整理 --

        #region --   基础调用 --

        /// <summary>
        /// 输出流的基本设置
        /// </summary>
        /// <param name="res">当前响应对象</param>
        /// <param name="isBuffer">是否缓冲输出并在处理完整个响应后发送它 默认false 为空则忽略</param>
        /// <param name="encoding">输出流的Http字符集 内容编码 如GB2312、UTF-8 等 为空则忽略</param>
        /// <param name="charset">输出流的Http字符集 客户端解释编码 如GB2312、UTF-8 等 为空则忽略</param>
        /// <param name="type">输出流的 HTTP MIME 类型 为空则忽略</param>
        /// <param name="length">指明长度 为空则忽略</param>
        /// <param name="fileName">输出 文件名 需指明</param>
        private static void outputSetting(HttpResponse res, bool? isBuffer, Encoding encoding, string charset, string type, string length, string fileName)
        {
            // 是否缓冲 默认false 如果为null 则忽略
            // true:缓冲（服务器处理完整个响应后 一次性发送 整体效率高，适用于处理时间较短的响应）
            // false:不缓冲（服务器处理响应的同时发送 首次响应快，适用于处理时间较长的响应）
            if (isBuffer != null)
            {
                res.Buffer = (bool)isBuffer;
            }

            // 输出流的Http字符集 用于指示输出流的内容编码 建议指明
            if (encoding != null)
            {
                res.ContentEncoding = encoding;
            }

            // 输出流的Http字符集 用于指示客户端以哪种编码显示（GB2312、UTF-8 ……） 建议忽略
            // 如果此处未设置或设置或设置了一个错误的值 则输出流默认以ContentEncoding的设置为准
            // 如果页面上有明文指定编码 如：<meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 则浏览器以此为准
            if (!string.IsNullOrEmpty(charset))
            {
                res.Charset = charset;
            }

            // 设置输出流的 HTTP MIME 类型
            // Excel类型：application/ms-excel
            // XML类型：text/xml
            // 字符流：application/octet-stream
            if (!string.IsNullOrEmpty(type))
            {
                res.ContentType = type;
            }

            // 指明文件长度 为空则忽略
            if (!string.IsNullOrEmpty(length))
            {
                res.AppendHeader("Content-Length", length);
            }

            // 通知浏览器下载文件而不是打开 文件名（文件名的编码方式是否需要指定？）
            res.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(fileName, Encoding.UTF8));
        }

        /// <summary>
        /// 将缓冲区的内容输出为指定格式的文件 从字符串
        /// </summary>
        /// <param name="isBuffer">是否缓冲输出并在处理完整个响应后发送它 默认false 为空则忽略</param>
        /// <param name="encoding">输出流的Http字符集 内容编码 如GB2312、UTF-8 等 为空则忽略</param>
        /// <param name="charset">输出流的Http字符集 客户端解释编码 如GB2312、UTF-8 等 为空则忽略</param>
        /// <param name="type">输出流的 HTTP MIME 类型 为空则忽略</param>
        /// <param name="length">指明长度 为空则忽略</param>
        /// <param name="fileName">输出 文件名 需指明</param>
        /// <param name="content">要输出的内容</param>
        private static void outputFileFromString(bool? isBuffer, Encoding encoding, string charset, string type, string length, string fileName, string content)
        {
            // 清空缓冲区 如有需要可以选择不清空
            HttpContext.Current.Response.Clear();

            // 当前输出流的基本设置
            outputSetting(HttpContext.Current.Response, isBuffer, encoding, charset, type, length, fileName);

            // 输出内容
            HttpContext.Current.Response.Write(content);
            HttpContext.Current.Response.End();
        }

        /// <summary>
        /// 将缓冲区的内容输出为指定格式的文件 从byte[]
        /// </summary>
        /// <param name="isBuffer">是否缓冲输出并在处理完整个响应后发送它 默认false 为空则忽略</param>
        /// <param name="encoding">输出流的Http字符集 内容编码 如GB2312、UTF-8 等 为空则忽略</param>
        /// <param name="charset">输出流的Http字符集 客户端解释编码 如GB2312、UTF-8 等 为空则忽略</param>
        /// <param name="type">输出流的 HTTP MIME 类型 为空则忽略</param>
        /// <param name="length">指明长度 为空则忽略</param>
        /// <param name="fileName">输出 文件名 需指明</param>
        /// <param name="content">要输出的内容</param>
        private static void outputFileFromBinary(bool? isBuffer, Encoding encoding, string charset, string type, string length, string fileName, byte[] content)
        {
            // 清空缓冲区 如有需要可以选择不清空
            HttpContext.Current.Response.Clear();

            // 当前输出流的基本设置
            outputSetting(HttpContext.Current.Response, isBuffer, encoding, charset, type, length, fileName);

            // 输出内容
            HttpContext.Current.Response.BinaryWrite(content);
            HttpContext.Current.Response.Flush(); //这一句有必要否？
            HttpContext.Current.Response.End();
        }

        /// <summary>
        /// 扩展1 将缓冲区的内容输出为指定格式的文件 从文件 Response.WriteFile
        /// </summary>
        /// <param name="isBuffer">是否缓冲输出并在处理完整个响应后发送它 默认false 为空则忽略</param>
        /// <param name="encoding">输出流的Http字符集 内容编码 如GB2312、UTF-8 等 为空则忽略</param>
        /// <param name="charset">输出流的Http字符集 客户端解释编码 如GB2312、UTF-8 等 为空则忽略</param>
        /// <param name="type">输出流的 HTTP MIME 类型 为空则忽略</param>
        /// <param name="length">指明长度 为空则忽略</param>
        /// <param name="fileName">输出 文件名 需指明</param>
        /// <param name="inputFileName">要输出的文件名（全名）</param>
        private static void outputFileFromFile(bool? isBuffer, Encoding encoding, string charset, string type, string length, string fileName, string inputFileName)
        {
            // 清空缓冲区 如有需要可以选择不清空
            HttpContext.Current.Response.Clear();

            // 当前输出流的基本设置
            outputSetting(HttpContext.Current.Response, isBuffer, encoding, charset, type, length, fileName);

            // 输出内容
            HttpContext.Current.Response.WriteFile(inputFileName);
            HttpContext.Current.Response.Flush(); //这一句有必要否？
            HttpContext.Current.Response.End();
        }

        // 扩展2 将缓冲区的内容输出为指定格式的文件 从另一响应块 Response.WriteSubstitution

        #endregion

        /// <summary>
        /// 将一个服务器端的本地文件以字符流的形式输出文件 这个有用到？
        /// </summary>
        /// <param name="filePath">文件路径 服务器端的文件</param>
        /// <param name="fileName">将要输出的文件名</param>
        public static void OutputFileFromLocal(string filePath, string fileName)
        {
            // 读文件到byte[] （也可以直接输出文件File）
            FileStream fs = new FileStream(filePath, FileMode.Open);
            byte[] bytes = new byte[(int)fs.Length]; // 此处fs.Length是long 而new byte[int] 要是fs.Length太大 转int会丢数据
            fs.Read(bytes, 0, bytes.Length);
            fs.Close();

            // 输出byte[]
            outputFileFromBinary(null, null, "", "application/octet-stream", "", fileName, bytes);
        }

        /// <summary>
        /// 下载文件 从一个绝对路径 这个什么时候会用到？与上面一个是否可以继集成
        /// </summary>
        /// <param name="url">文件的绝对路径</param>
        /// <param name="fileName">将要输出的文件名</param>
        public static void OutputFileFromUrl(string url, string fileName)
        {
            // 读文件
            FileInfo tagFile = new FileInfo(url);

            //try
            //{
            //    HttpContext.Current.Response.Clear();
            //    HttpContext.Current.Response.ContentType = "application/octet-stream";
            //    string br = HttpContext.Current.Request.Browser.Browser;
            //    if (br.ToUpper() == "IE")
            //        HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));
            //    else
            //        HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + fileName);
            //    HttpContext.Current.Response.AppendHeader("Content-Length", DownloadFile.Length.ToString());
            //    HttpContext.Current.Response.WriteFile(DownloadFile.FullName);
            //    HttpContext.Current.Response.Flush();
            //    HttpContext.Current.Response.End();
            //}
            //catch (FileNotFoundException)
            //{
            //    throw new Exception("文件不存在");
            //}

            // 输出文件 上述原文中 文件可能不存在？测试
            outputFileFromFile(null, null, "", "application/octet-stream", tagFile.Length.ToString(), fileName, tagFile.FullName);
        }

        /// <summary>
        /// 输出一个字符串为指定文件 这个是否会用到？
        /// </summary>
        /// <param name="content">将要输出的字符串</param>
        /// <param name="contentType">输出的 MIME 类型 如：application/ms-excel</param>
        /// <param name="fileName">将要输出的文件名</param>
        public static void OutputFileFromStr(string content, string contentType, string fileName)
        {
            outputFileFromString(null, Encoding.Default, "UTF-8", contentType, "", fileName, content);
        }

        /// <summary>
        /// 将缓冲中的内容输出为XML文档 直接显示在网页上
        /// </summary>
        /// <param name="content">xml内容</param>
        public static void OutputXmlDoc(string content)
        {
            outputFileFromString(null, null, null, "text/xml", null, "XmlDoc", content);
        }

        /// <summary>
        /// 输出Excel文件到客户端
        /// </summary>
        /// <param name="fileName">将输出的文件名</param>
        /// <param name="content">要输出的内容</param>
        public static void OutputExcelDoc(string fileName, string content)
        {
            outputFileFromString(true, Encoding.GetEncoding("GB2312"), "GB2312", "application/ms-excel", null, fileName, content);
        }

        #endregion

        #region -- 文件删除 --

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>0:成功删除；1:文件路径为空;2:文件不存在</returns>
        public static int DeleteFile(string filePath)
        {

            if (string.IsNullOrEmpty(filePath))
            {
                // 文件路径为空
                return 1;
            }
            if (!File.Exists(filePath))
            {
                // 文件不存在
                return 2;
            }
            File.Delete(filePath);
            return 0;
        }

        #endregion

        #region -- 文件读写 --

        /// <summary>
        /// 读文件内容到字符串
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns></returns>
        public static string ReadFromFile(string filePath)
        {
            string contents = "";
            StreamReader sr = new StreamReader(filePath, System.Text.Encoding.GetEncoding("gb2312"));
            contents = sr.ReadToEnd();
            sr.Close();
            return contents;
        }

        /// <summary>
        /// 读Excel内容到DataTable
        /// </summary>
        /// <param name="path">xls在服务器上的绝对路径</param>
        /// <param name="fields">要读取的字段，以,分割，至少要有一个字段</param>
        /// <param name="fExt">扩展名</param>
        /// <param name="cueInfo"></param>
        /// <returns>DataTable，为null读取失败</returns>
        public static DataTable GetDataListFromExcel(string path, string fields, string fExt, ref string cueInfo)
        {
            string connStr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Extended Properties=Excel 8.0;" + "data source=" + path;

            if (fExt == ".xlsx")
            {
                connStr = "Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties=Excel 12.0 XML;Data Source=" + path;
            }

            DataTable dtSell = null;
            try
            {
                DataSet dsSell = new DataSet();
                using (OleDbConnection odconn = new OleDbConnection(connStr))
                {
                    using (OleDbDataAdapter odda = new OleDbDataAdapter(@"SELECT " + fields + " FROM [Sheet1$]", odconn))
                    {
                        odda.Fill(dsSell, "sell");
                        if (dsSell != null && dsSell.Tables.Count > 0)
                        {
                            dtSell = dsSell.Tables[0];

                        }
                    }
                }
            }
            catch
            {
                cueInfo += "从Excel读取数据失败!!<br />";
            }
            return dtSell;
        }

        #endregion
    }
}